package com.thread.sync.sync10;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyCustom01 {

    public static void main(String[] args) {
        //有界队列自定义线程池
        /**在使用有界队列时，如果有任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，
         * 若大于corePoolSize，则会将任务加入队列，
         * 若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，
         * 若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。
         */
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1,   //核心线程数
                2,   //最大线程数
                60,   //空闲时回收时间
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(3),//指定队列//指定队列
                //DiscardOldestPolicy :丢弃最老的请求,即当6进来时,将队列中最早的2丢弃,执行6
                //new ThreadPoolExecutor.DiscardOldestPolicy()//指定拒绝策略.不指定默认抛异常
                //自定义拒绝策略
                new RejectedExecutionHandler() {
                    @Override        //r:被拒绝任务     executor 当前线程池
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        //实例工作中默认策略都不可取,一般是把拒绝的任务记录日志,然后空闲时间解析再重新执行
                        //或者直接返回客户端,让他稍后再提交此任务
                        System.out.println("自定义处理..");
                        System.out.println("当前被拒绝任务为：" + r.toString());
                        System.out.println(executor.getPoolSize());
                    }
                }
        );
        MyTask mt1 = new MyTask(1, "任务1");
        MyTask mt2 = new MyTask(2, "任务2");
        MyTask mt3 = new MyTask(3, "任务3");
        MyTask mt4 = new MyTask(4, "任务4");
        MyTask mt5 = new MyTask(5, "任务5");
        MyTask mt6 = new MyTask(6, "任务6");
        pool.execute(mt1);
        pool.execute(mt2);//如果有两个任务,则会将第二个任务入队,等待核心线程线程空闲
        pool.execute(mt3);//同上
        pool.execute(mt4);//同上,知道队列满 为止
        pool.execute(mt5);//当有5个任务时,队列已满,则会创建第二个线程
        pool.execute(mt6); //有6个时,此时队列已满,且当前线程达到最大线程数,所以无法执行,执行拒绝策略
        //关闭,等到所有线程空闲时才会关闭
        pool.shutdown();
    }
}

